package native

import (
	"gvm/native/basic"
	"gvm/native/java/io"
	"gvm/native/java/lang"
	"gvm/native/java/security"
	"gvm/native/sun/misc"
	"gvm/native/sun/reflect"
	"gvm/rtda"
)

var registry = map[string]basic.NativeMethod{}

func Register(className string, nm *basic.NaMethod) {
	key := className + "~" + nm.MethodName + "~" + nm.MethodDescriptor
	registry[key] = nm.Method
}

func Registers(className string, nms []*basic.NaMethod) {
	for _, nm := range nms {
		Register(className, nm)
	}
}

func FindNativeMethod(className string, methodName string, methodDescriptor string) basic.NativeMethod {
	key := className + "~" + methodName + "~" + methodDescriptor
	if method, ok := registry[key]; ok {
		return method
	}
	if methodDescriptor == "()V" && (methodName == "registerNatives" || methodName == "initIDs") {
		return emptyNativeMethod
	}
	if len(registry) == 0 {
		Registers(security.AccessController())

		Registers(io.FileDescriptor())
		Registers(io.FileInputStream())
		Registers(io.FileOutputStream())

		Registers(lang.RegisterClass())
		Registers(lang.RegisterDouble())
		Registers(lang.RegisterFloat())
		Registers(lang.RegisterObject())
		Registers(lang.RegisterString())
		Registers(lang.RegisterSystem())
		Registers(lang.RegisterThread())
		Registers(lang.RegisterThrowable())

		Registers(misc.RegisterVm())
		Registers(misc.RegisterUnsafe())
		Registers(reflect.RegisterReflection())
		return FindNativeMethod(className, methodName, methodDescriptor)
	}
	return nil
}

func emptyNativeMethod(frame *rtda.JFrame) {
	//do nothing
}
